<template>
  <el-dialog
    v-model="visible"
    :title="`快速测试 - ${vulnerability.name || ''}`"
    width="900px"
    :close-on-click-modal="false"
    @close="handleClose"
  >
    <div class="test-content" v-loading="loading">
      <!-- 目标配置 -->
      <el-card class="config-card" shadow="never">
        <template #header>
          <div class="card-header">
            <span class="card-title">目标配置</span>
          </div>
        </template>
        <el-form :model="scanForm" label-width="120px">
          <el-form-item label="目标地址" required>
            <el-input
              v-model="scanForm.target_url"
              placeholder="请输入目标URL，例如: http://192.168.1.100:7001"
              :disabled="isScanning"
            />
          </el-form-item>
          <el-form-item label="使用POC">
            <el-input :value="pocFileName" disabled placeholder="自动选择" />
          </el-form-item>
          <el-form-item>
            <el-checkbox v-model="scanForm.detectOnly" :disabled="isScanning">
              仅检测漏洞存在 (不执行攻击)
            </el-checkbox>
          </el-form-item>
          <el-form-item>
            <el-button
              type="primary"
              @click="handleStartScan"
              :loading="isScanning"
              :disabled="!scanForm.target_url"
            >
              开始扫描
            </el-button>
          </el-form-item>
        </el-form>
      </el-card>

      <!-- 扫描进度 -->
      <el-card
        v-if="isScanning || scanStatus"
        class="progress-card"
        shadow="never"
      >
        <template #header>
          <div class="card-header">
            <span class="card-title">扫描进度</span>
          </div>
        </template>
        <div class="progress-content">
          <div class="status-info">
            <span class="status-label">状态:</span>
            <el-tag
              :type="
                scanStatus?.status === 'completed'
                  ? 'success'
                  : scanStatus?.status === 'failed'
                  ? 'danger'
                  : scanStatus?.status === 'running'
                  ? 'warning'
                  : 'info'
              "
            >
              {{
                scanStatus?.status === "running"
                  ? "⏳ 正在扫描..."
                  : scanStatus?.status === "completed"
                  ? "✅ 扫描完成"
                  : scanStatus?.status === "failed"
                  ? "❌ 扫描失败"
                  : "⏸️ 等待中"
              }}
            </el-tag>
          </div>
          <div class="progress-bar-wrapper" v-if="scanStatus">
            <span class="progress-label">进度:</span>
            <el-progress
              :percentage="scanStatus.progress || 0"
              :status="
                scanStatus.status === 'failed'
                  ? 'exception'
                  : scanStatus.status === 'completed'
                  ? 'success'
                  : undefined
              "
            />
          </div>
          <div class="log-section" v-if="scanStatus?.logs?.length">
            <div class="log-label">日志:</div>
            <div class="log-content">
              <div
                v-for="(log, index) in scanStatus.logs"
                :key="index"
                class="log-item"
              >
                {{ log }}
              </div>
            </div>
          </div>
        </div>
      </el-card>

      <!-- 扫描结果 -->
      <el-card
        v-if="scanResult && scanStatus?.status === 'completed'"
        class="result-card"
        shadow="never"
      >
        <template #header>
          <div class="card-header">
            <span class="card-title">扫描结果</span>
          </div>
        </template>
        <div class="result-content">
          <div
            v-if="scanResult.total_vulnerabilities > 0"
            class="result-success"
          >
            <el-icon class="success-icon"><CircleCheck /></el-icon>
            <span class="result-text">发现漏洞!</span>
          </div>
          <div v-else class="result-info">
            <el-icon class="info-icon"><InfoFilled /></el-icon>
            <span class="result-text">未发现漏洞</span>
          </div>

          <div
            v-if="scanResult.results && scanResult.results.length > 0"
            class="vulnerability-results"
          >
            <div
              v-for="(result, index) in scanResult.results"
              :key="index"
              class="vulnerability-item"
            >
              <el-descriptions :column="1" border>
                <el-descriptions-item label="漏洞ID">
                  {{ result.vulnerability_id || "-" }}
                </el-descriptions-item>
                <el-descriptions-item label="漏洞名称">
                  {{ result.name || "-" }}
                </el-descriptions-item>
                <el-descriptions-item label="严重程度">
                  <el-tag
                    :type="
                      result.severity === 'critical'
                        ? 'danger'
                        : result.severity === 'high'
                        ? 'warning'
                        : result.severity === 'medium'
                        ? 'info'
                        : result.severity === 'low'
                        ? 'success'
                        : ''
                    "
                    size="small"
                  >
                    {{ getSeverityText(result.severity) }}
                  </el-tag>
                </el-descriptions-item>
                <el-descriptions-item label="置信度">
                  {{ result.confidence || 0 }}%
                </el-descriptions-item>
                <el-descriptions-item label="CVSS评分">
                  {{ result.cvss_score || "-" }}
                </el-descriptions-item>
                <el-descriptions-item label="检测时间">
                  {{ result.detected_at || "-" }}
                </el-descriptions-item>
                <el-descriptions-item label="证明信息" v-if="result.evidence">
                  {{ result.evidence }}
                </el-descriptions-item>
                <el-descriptions-item label="原始输出" v-if="result.raw_output">
                  <pre class="raw-output">{{ result.raw_output }}</pre>
                </el-descriptions-item>
              </el-descriptions>
            </div>
          </div>

          <div class="result-summary" v-if="scanResult.summary">
            <div class="summary-title">统计摘要:</div>
            <div class="summary-items">
              <el-tag type="danger" size="small"
                >严重: {{ scanResult.summary.critical || 0 }}</el-tag
              >
              <el-tag type="warning" size="small"
                >高危: {{ scanResult.summary.high || 0 }}</el-tag
              >
              <el-tag type="info" size="small"
                >中危: {{ scanResult.summary.medium || 0 }}</el-tag
              >
              <el-tag type="success" size="small"
                >低危: {{ scanResult.summary.low || 0 }}</el-tag
              >
              <el-tag size="small"
                >信息: {{ scanResult.summary.info || 0 }}</el-tag
              >
            </div>
          </div>
        </div>
      </el-card>
    </div>

    <template #footer>
      <el-button @click="handleClose">关闭</el-button>
      <el-button
        v-if="scanResult && scanStatus?.status === 'completed'"
        type="primary"
        @click="handleExportResult"
      >
        导出结果
      </el-button>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, computed, watch, onUnmounted } from "vue";
import { ElMessage } from "element-plus";
import { CircleCheck, InfoFilled } from "@element-plus/icons-vue";
import {
  createVulnerabilityScan,
  getVulnerabilityScanStatus,
  getVulnerabilityScanResult,
} from "../../../servers";

// 定义props
const props = defineProps({
  modelValue: { type: Boolean, default: false },
  vulnerability: {
    type: Object,
    default: () => ({}),
  },
});

// 定义emits
const emit = defineEmits<{
  (e: "update:modelValue", value: boolean): void;
}>();

// visible computed 属性
const visible = computed({
  get: () => props.modelValue,
  set: (value: boolean) => emit("update:modelValue", value),
});

const loading = ref(false);
const isScanning = ref(false);
const taskId = ref<string>("");
const scanStatus = ref<any>(null);
const scanResult = ref<any>(null);
let statusPollingTimer: any = null;

// 扫描表单
const scanForm = ref({
  target_url: "",
  detectOnly: true, // 默认仅检测，不执行攻击
});

// POC文件名
const pocFileName = computed(() => {
  return (
    props.vulnerability?.file_name ||
    props.vulnerability?.poc_file ||
    "自动选择"
  );
});

// 获取严重程度文本
const getSeverityText = (severity: string): string => {
  const map: Record<string, string> = {
    critical: "严重",
    high: "高危",
    medium: "中危",
    low: "低危",
    info: "信息",
    unknown: "未知",
  };
  return map[severity] || severity || "-";
};

// 开始扫描
const handleStartScan = async () => {
  if (!scanForm.value.target_url) {
    ElMessage.warning("请输入目标URL");
    return;
  }

  loading.value = true;
  isScanning.value = true;
  scanStatus.value = null;
  scanResult.value = null;

  try {
    // 创建扫描任务
    const pocFiles = props.vulnerability?.file_name
      ? [props.vulnerability.file_name]
      : [];

    const { data } = await createVulnerabilityScan({
      target_url: scanForm.value.target_url,
      poc_files: pocFiles,
      scan_mode: scanForm.value.detectOnly ? "detect" : "exploit",
      save_result: true,
      vulnerability_id: props.vulnerability.vulnerability_id,
    });

    if (data?.task_id) {
      taskId.value = data.task_id;
      ElMessage.success("扫描任务创建成功");
      // 开始轮询状态
      startStatusPolling();
    } else {
      ElMessage.error("创建扫描任务失败");
      isScanning.value = false;
    }
  } catch (error: any) {
    ElMessage.error(error?.message || "创建扫描任务失败");
    isScanning.value = false;
  } finally {
    loading.value = false;
  }
};

// 开始状态轮询
const startStatusPolling = () => {
  if (statusPollingTimer) {
    clearInterval(statusPollingTimer);
  }

  const pollStatus = async () => {
    if (!taskId.value) return;

    try {
      const { data } = await getVulnerabilityScanStatus(taskId.value);
      if (data) {
        scanStatus.value = data;

        // 如果扫描完成，获取结果
        if (data.status === "completed" || data.status === "failed") {
          isScanning.value = false;
          clearInterval(statusPollingTimer);
          statusPollingTimer = null;

          if (data.status === "completed") {
            await fetchScanResult();
          }
        }
      }
    } catch (error: any) {
      console.error("查询扫描状态失败:", error);
    }
  };

  // 立即查询一次
  pollStatus();
  // 每2秒轮询一次
  statusPollingTimer = setInterval(pollStatus, 2000);
};

// 获取扫描结果
const fetchScanResult = async () => {
  if (!taskId.value) return;

  try {
    const { data } = await getVulnerabilityScanResult(taskId.value);
    if (data) {
      scanResult.value = data;
    }
  } catch (error: any) {
    ElMessage.error(error?.message || "获取扫描结果失败");
  }
};

// 导出结果
const handleExportResult = () => {
  if (!scanResult.value) return;

  const resultText = JSON.stringify(scanResult.value, null, 2);
  const blob = new Blob([resultText], { type: "application/json" });
  const url = URL.createObjectURL(blob);
  const link = document.createElement("a");
  link.href = url;
  link.download = `scan_result_${taskId.value}_${Date.now()}.json`;
  link.click();
  URL.revokeObjectURL(url);
  ElMessage.success("结果导出成功");
};

// 关闭弹窗
const handleClose = () => {
  // 清理轮询
  if (statusPollingTimer) {
    clearInterval(statusPollingTimer);
    statusPollingTimer = null;
  }
  // 重置状态
  isScanning.value = false;
  scanStatus.value = null;
  scanResult.value = null;
  taskId.value = "";
  scanForm.value = {
    target_url: "",
    detectOnly: true,
  };
  emit("update:modelValue", false);
};

// 监听弹窗关闭，清理定时器
watch(visible, (newVal) => {
  if (!newVal && statusPollingTimer) {
    clearInterval(statusPollingTimer);
    statusPollingTimer = null;
  }
});

// 组件卸载时清理
onUnmounted(() => {
  if (statusPollingTimer) {
    clearInterval(statusPollingTimer);
  }
});
</script>

<style scoped lang="scss">
.test-content {
  .config-card,
  .progress-card,
  .result-card {
    margin-bottom: 20px;

    &:last-child {
      margin-bottom: 0;
    }
  }

  .card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;

    .card-title {
      font-weight: bold;
      font-size: 16px;
    }
  }

  .progress-content {
    .status-info {
      margin-bottom: 15px;
      display: flex;
      align-items: center;
      gap: 10px;

      .status-label {
        font-weight: 500;
      }
    }

    .progress-bar-wrapper {
      margin-bottom: 15px;
      display: flex;
      align-items: center;
      gap: 10px;

      .progress-label {
        min-width: 50px;
        font-weight: 500;
      }
    }

    .log-section {
      margin-top: 15px;

      .log-label {
        font-weight: 500;
        margin-bottom: 10px;
      }

      .log-content {
        max-height: 200px;
        overflow-y: auto;
        padding: 10px;
        background-color: #f5f7fa;
        border-radius: 4px;
        font-family: "Courier New", monospace;
        font-size: 12px;

        .log-item {
          margin-bottom: 5px;
          color: #606266;

          &:last-child {
            margin-bottom: 0;
          }
        }
      }
    }
  }

  .result-content {
    .result-success,
    .result-info {
      display: flex;
      align-items: center;
      gap: 10px;
      margin-bottom: 20px;
      font-size: 18px;
      font-weight: bold;

      .success-icon {
        color: #67c23a;
        font-size: 24px;
      }

      .info-icon {
        color: #909399;
        font-size: 24px;
      }
    }

    .vulnerability-results {
      margin-bottom: 20px;

      .vulnerability-item {
        margin-bottom: 15px;

        &:last-child {
          margin-bottom: 0;
        }
      }
    }

    .raw-output {
      margin: 0;
      padding: 10px;
      background-color: #f5f7fa;
      border-radius: 4px;
      font-family: "Courier New", monospace;
      font-size: 12px;
      white-space: pre-wrap;
      word-break: break-word;
      max-height: 200px;
      overflow-y: auto;
    }

    .result-summary {
      margin-top: 20px;
      padding-top: 20px;
      border-top: 1px solid #ebeef5;

      .summary-title {
        font-weight: 500;
        margin-bottom: 10px;
      }

      .summary-items {
        display: flex;
        gap: 10px;
        flex-wrap: wrap;
      }
    }
  }
}
</style>
